import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;

import javax.swing.JApplet;

import br.com.pentagrama.dto.InfoServico;
import br.com.pentagrama.exception.ParseConfException;
import br.com.pentagrama.service.IDownloadUpload;
import br.com.pentagrama.service.ILog;
import br.com.pentagrama.service.ITestadorAmbiente;
import br.com.pentagrama.service.impl.ParametrosService;
import br.com.pentagrama.util.NumberUtil;
import br.com.pentagrama.util.ParseUtil;
import br.com.pentagrama.util.Sistema;
import br.com.pentagrama.util.StringScape;

@SuppressWarnings("serial")
public class DadosRede extends JApplet {

	private static String ERRO_INESPERADO = "[ERRO] Erro inesperado ao testar o ambiente. Por favor consulte o administrador do sistema.";
	
	private String linkArquivo = "";
	
	private ITestadorAmbiente testador;
	
	private IDownloadUpload velocidadeService;
	
	private ILog log;
	
	private Long latenciaPing = 0L;
	
	private InfoServico videoDesktopMovel;
	
	private InfoServico videoSalasVydio;
	
	private InfoServico videoSalasOutras;
	
	private InfoServico gravacao;
	
	private InfoServico webCasting;
	
	private Double velocidadeDownload = 0.0;
	
	private Double velocidadeUpload = 0.0;
	
	private String qualidadeMaxima = "-";
	
	private long tempo;

	public String relatorio() {
		return linkArquivo;
	}
	
//	public void gerarRelatorio() {
//		try {
//			String conteudo = log.ler();
//			log.debug(Level.INFO, "Executando javascript para armazenar o relatorio: " + conteudo);
//			executeJS(String.format("preencherRelatorio(\"%s\")", StringScape.escapeJavaScript(conteudo)));
//		} catch (Exception e) {
//			jsMensagem(ERRO_INESPERADO);
//			log.debug(Level.SEVERE, "Erro ao gerar relatório", e);
//		}
//	}
	
	public void executeJS(String comando) {
		try {
			getAppletContext().showDocument(
					new URL("javascript:" + comando ));

		} catch (MalformedURLException excpetion) {
			// faz nada
		}
	}
	
	public void jsMensagem(String mensagem) {
		executeJS(String.format("alert('%s')", mensagem));
	}
	
	public void jsReportProcess(String mensagem) {
		executeJS(String.format("reportProcess('%s')", mensagem));
	}
	
	
	public void jsInicio() {
		executeJS("inicio()");
	}
	
	public void jsFim() {
		executeJS("fim()");
	}
	
	public void jsValores() {
		String conteudo = log.ler();
		executeJS(String.format("setGrafico('%s')", NumberUtil.formatDecimal(velocidadeDownload/1024)));
		executeJS(String.format("setDownload('%s')", ParseUtil.formatarVelocidade(velocidadeDownload)));
		executeJS(String.format("setUpload('%s')", ParseUtil.formatarVelocidade(velocidadeUpload)));
		executeJS(String.format("setQualidadeMaxima('%s')", qualidadeMaxima));
		executeJS(String.format("setLatencia('%s')", latenciaPing + ""));
		
		for(String texto : log.getLista()) {
			executeJS(String.format("preencherRelatorio(\"%s\")", StringScape.escapeJavaScript(texto)));
		}
		
		
		
		InfoServico[] servicos = new InfoServico[]{videoDesktopMovel, videoSalasVydio, videoSalasOutras, gravacao, webCasting};

		int i = 0;
		for (InfoServico infoServico : servicos) {
			executeJS(String.format("setServico(%d,%b,%b,%b)", ++i, infoServico.isIpStatus(), infoServico.isTcpStatus(),infoServico.isUdpStatus()));
		}
	}
	
	/**
	 * Inicializa valores comuns
	 */
	public void init() {
		tempo = System.currentTimeMillis();
		log = Sistema.getLog();
		log.limpar();
		
		jsReportProcess("Iniciando testes...");
		log.info("INICIO DOS TESTES DE AMBIENTE");
		
		String arqConf = this.getParameter("ARQ_CONF");
		if (arqConf == null) {
			arqConf = "http://pabloreis.site50.net/apache/teste.conf";
		} else {
			arqConf = getCodeBase().toString() + arqConf;
		}
		
		ParametrosService parametrosService = ParametrosService.getInstance(arqConf);
		
		jsReportProcess("Carregando Arquivo de configuração...");
		try {
			parametrosService.carregarParametros();
		} catch (ParseConfException e) {
			e.printStackTrace();
			log.debug(Level.INFO, "Falha ao carregar arquivo de configuração: " + arqConf);
		}
		
		log.debug(Level.INFO, "Arquivo de configuração carregado: " + arqConf);
		testador = Sistema.getTestadorAmbiente();
		URL url = getCodeBase();
		velocidadeService = Sistema.getDownloadUpload(url);
	}
	
	/**
	 * Primeiro método do applet a ser executado.
	 */
	public void start() {
		log.info("In\u00EDcio dos testes");
		jsInicio();
		try {
			testarAmbiente();
			log.info("Testes Finalizados com sucesso");
			jsReportProcess("Testes Finalizados com sucesso.");
		} catch (Exception e) {
			jsMensagem(ERRO_INESPERADO);
			log.erro(ERRO_INESPERADO, e);
			e.printStackTrace();
		} finally {
			jsValores();
			jsFim();
		}
		
		tempo = (System.currentTimeMillis() - tempo)/1000;
		log.info("Finalizado em " + tempo + " segundos");
	}
	
	/**
	 * Método para testar o ambiente.
	 */
	public void testarAmbiente() {
		try {
			
			log.info("Teste de Ping Inicial");
			jsReportProcess("Executando teste de ping");
			latenciaPing = testador.getLatenciaPing(getCodeBase().toString());
			log.info("Lat\u00EAncia: " + latenciaPing + "ms");
			log.info("Testando Videoconfer\u00EAncia Desktop/M\u00F3vel");
			jsReportProcess("Testando Videoconferência Desktop/Móvel");
			videoDesktopMovel = testador.getVideoDesktopMovel();
			log.info("Testando Videoconfer\u00EAncia com Salas F\u00EDsicas Vidyo");
			jsReportProcess("Testando Videoconferência com Salas Físicas Vidyo");
			videoSalasVydio = testador.getVideoSalasVydio();
			log.info("Testando Videoconfer\u00EAncia com Salas Outros Fabricantes");
			jsReportProcess("Testando Videoconferência com Salas Outros Fabricantes");
			videoSalasOutras = testador.getVideoSalasOutras();
			log.info("Testando Grava\u00E7\u00E3o");
			jsReportProcess("Testando Gravação");
			gravacao = testador.getGravacao();
			log.info("Testando WebCasting");
			jsReportProcess("Testando WebCasting");
			webCasting = testador.getWebCasting();
			log.info("Teste de download");
			jsReportProcess("Teste de download");
			velocidadeDownload = velocidadeService.doDownload();
			log.info("Download:  " + ParseUtil.formatarVelocidade(velocidadeDownload));
			log.info("Teste de upload");
			jsReportProcess("Teste de upload");
			velocidadeUpload = velocidadeService.doUpload();
			log.info("Upload Kbits/segundo:  " + ParseUtil.formatarVelocidade(velocidadeUpload));
			qualidadeMaxima = getQualidadeMaxima(velocidadeDownload/1024);
			log.info("Determinada qualidade m\u00E1xima: " + qualidadeMaxima);
			jsReportProcess("Verificando qualidade máxima");
		} catch (ParseConfException e) {
			log.erro(ERRO_INESPERADO, e);
			e.printStackTrace();
		}
	}
	
	public void resumo() {
		
		log.info("RESULTADO DOS TESTES");
		
		InfoServico[] servicos = new InfoServico[]{videoDesktopMovel, videoSalasVydio, videoSalasOutras, gravacao, webCasting};
		//log.escrever("Latência: " + latenciaPing);
		
		for (InfoServico infoServico : servicos) {
			log.info(infoServico.getNome());
			log.info("IP: " + infoServico.isIpStatus());
			log.info("TCP: " + infoServico.isTcpStatus());
			log.info("UDP: " + infoServico.isUdpStatus());
		}
		
		log.info("Download: " + ParseUtil.formatarVelocidade(velocidadeDownload));
		log.info("Upload: " + ParseUtil.formatarVelocidade(velocidadeUpload));
		log.info("Qualidade M\u00E1xima: " + qualidadeMaxima);
		
		System.out.println(log.ler());
	}
	
	public String getQualidadeMaxima(Double kbits) {
		
		if(kbits == null) {
			return "-";
		}		
		
		if(kbits >= 384 && kbits < 768) {
			return "CIF";
		}
		if(kbits >= 768 && kbits < 1024) {
			return "SD";
		}
		if(kbits >= 1024 && kbits < 2048) {
			return "HD";
		}
		if(kbits >= 2048) {
			return "Full-HD";
		}
		return "-"; //menor que 384k
	}
}

